package com.sunzm.dynamic_rule.service.impl;

import com.sunzm.dynamic_rule.pojo.RuleAtomicParam;
import com.sunzm.dynamic_rule.pojo.RuleParam;
import com.sunzm.dynamic_rule.service.UserActionSequenceQueryService;
import com.sunzm.dynamic_rule.utils.ConnectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.List;

/**
 * 行为序列类路径匹配查询service，clickhouse实现
 */
public class UserActionSequenceQueryServiceClickhouseImpl implements UserActionSequenceQueryService {
    private static final Logger logger = LoggerFactory.getLogger(UserActionSequenceQueryServiceClickhouseImpl.class);

    private static Connection conn;

    static {
        try {
            conn = ConnectionUtils.getClickhouseConnection();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean queryActionSequence(String deviceId, RuleParam ruleParam) throws Exception {

        //用户行为序列类规则
        List<RuleAtomicParam> userActionSequenceParams = ruleParam.getUserActionSequenceParams();

        // 获取规则中，路径模式的总步骤数
        int totalStep = userActionSequenceParams.size();

        RuleAtomicParam ruleAtomicParam = userActionSequenceParams.get(0);

        // 取出查询sql
        String sql = ruleParam.getActionSequenceQuerySql();

        /*Statement st = conn.createStatement();
        ResultSet resultSet = st.executeQuery(sql);*/

        PreparedStatement ps = conn.prepareStatement(sql);
        // 需要将sql中的deviceId占位符替换成真实deviceId
        ps.setString(1, deviceId);
        ps.setLong(2, ruleAtomicParam.getRangeStart());
        ps.setLong(3, ruleAtomicParam.getRangeEnd());
        ResultSet resultSet = ps.executeQuery();

        // 执行查询
        long s = System.currentTimeMillis();

        /* 从返回结果中进行条件判断
         * ┌─deviceId─┬─isMatch3─┬─isMatch2─┬─isMatch1─┐
         * │ 000001   │       0  │        0 │        1 │
         * └──────────┴──────────┴──────────┴──────────┘
         * 重要逻辑： 查询结果中有几个1，就意味着最大完成步骤是几！！！
         */
        int maxStep = 0;
        while (resultSet.next()) {   // 返回结果最多就1行，这个while就走一次!!!
            // 对一行结果中的1进行累加，累加结果即完成的最大步骤数
            for (int i = 2; i < totalStep + 2; i++) {
                maxStep += resultSet.getInt(i);
            }
        }
        long e = System.currentTimeMillis();

        // 将结果塞回规则参数
        ruleParam.setUserActionSequenceQueriedMaxStep(ruleParam.getUserActionSequenceQueriedMaxStep() + maxStep);

        logger.info("clickhouse序列查询，耗时:{},查询到的最大步数:{},条件总步数:{}", (e - s), maxStep, totalStep);
        return maxStep == totalStep;
    }
}
